type CNum = (Int->Int)->Int->Int;
var PAIR  = $x:CNum => $y:CNum => $f:CNum->CNum->CNum => f(x)(y);
var LEFT  = $p:((CNum->CNum->CNum)->CNum) => p($x:CNum=>$y:CNum=>x);
var RIGHT = $p:((CNum->CNum->CNum)->CNum) => p($x:CNum=>$y:CNum=>y);
var ZERO : CNum;
ZERO  = $f:(Int->Int)=>$x:Int=>x;
var SUCC   = $m:CNum=>$f:(Int->Int)=>$x:Int=>f(m(f)(x));
var ONE    = SUCC(ZERO);
var TWO    = SUCC(ONE);
var THREE  = SUCC(TWO);
var FOUR   = SUCC(THREE);
var FIVE   = SUCC(FOUR);
var MUL    = $m:CNum=>$n:CNum=>$f:(Int->Int)=>$x:Int=>m(n(f))(x);
var INC    = $x:Int => x + 1;
var TO_INT = $f:CNum => f(INC)(0);
var pair0  = PAIR(ONE)(FIVE);
var pair1  = PAIR(TWO)(MUL(FOUR)(FIVE));
println(TO_INT(LEFT(pair0)));
println(TO_INT(RIGHT(pair0)));
println(TO_INT(LEFT(pair1)));
println(TO_INT(RIGHT(pair1)));
